$(document).ready(function () {

	/**
	 * WYSIWYG - jQuery plugin 0.97
	 * (0.97.2 - From infinity)
	 *
	 * Copyright (c) 2008-2009 Juan M Martinez, 2010-2011 Akzhan Abdulin and all contributors
	 * https://github.com/akzhan/jwysiwyg
	 *
	 * Dual licensed under the MIT and GPL licenses:
	 *   http://www.opensource.org/licenses/mit-license.php
	 *   http://www.gnu.org/licenses/gpl.html
	 *
	 */
	
	/*jslint browser: true, forin: true */

	(function ($) {
		"use strict";
		/* Wysiwyg namespace: private properties and methods */
	
		var console = window.console ? window.console : {
			log: $.noop,
			error: function (msg) {
				$.error(msg);
			}
		};
		var supportsProp = (('prop' in $.fn) && ('removeProp' in $.fn));
	
		function Wysiwyg() {
			this.controls = {
				bold: {
					groupIndex: 0,
					visible: false,
					tags: ["b", "strong"],
					css: {
						fontWeight: "bold"
					},
					tooltip: "Bold",
					hotkey: {"ctrl": 1, "key": 66}
				},
	
				copy: {
					groupIndex: 8,
					visible: false,
					tooltip: "Copy"
				},
	
				createLink: {
					groupIndex: 6,
					visible: false,
					exec: function () {
						var self = this;
						if ($.wysiwyg.controls && $.wysiwyg.controls.link) {
							$.wysiwyg.controls.link.init(this);
						} else if ($.wysiwyg.autoload) {
							$.wysiwyg.autoload.control("wysiwyg.link.js", function () {
								self.controls.createLink.exec.apply(self);
							});
						} else {
							console.error("$.wysiwyg.controls.link not defined. You need to include wysiwyg.link.js file");
						}
					},
					tags: ["a"],
					tooltip: "Create link"
				},
	
				cut: {
					groupIndex: 8,
					visible: false,
					tooltip: "Cut"
				},
	
				decreaseFontSize: {
					groupIndex: 9,
					visible: false,
					tags: ["small"],
					tooltip: "Decrease font size",
					exec: function () {
						this.decreaseFontSize();
					}
				},
	
				h1: {
					groupIndex: 7,
					visible: false,
					className: "h1",
					command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h1>" : "h1",
					tags: ["h1"],
					tooltip: "Header 1"
				},
	
				h2: {
					groupIndex: 7,
					visible: false,
					className: "h2",
					command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h2>" : "h2",
					tags: ["h2"],
					tooltip: "Header 2"
				},
	
				h3: {
					groupIndex: 7,
					visible: false,
					className: "h3",
					command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h3>" : "h3",
					tags: ["h3"],
					tooltip: "Header 3"
				},
				h4: {
					groupIndex: 7,
					visible: false,
					className: "h4",
					command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h4>" : "h4",
					tags: ["h4"],
					tooltip: "Header 4"
				},
	
				h5: {
					groupIndex: 7,
					visible: false,
					className: "h5",
					command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h5>" : "h5",
					tags: ["h5"],
					tooltip: "Header 5"
				},
	
				h6: {
					groupIndex: 7,
					visible: false,
					className: "h6",
					command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h6>" : "h6",
					tags: ["h6"],
					tooltip: "Header 6"
				},
	
				highlight: {
					tooltip:     "Highlight",
					className:   "highlight",
					groupIndex:  1,
					visible:     false,
					css: {
						backgroundColor: "rgb(255, 255, 102)"
					},
					exec: function () {
						var command, node, selection, args;
	
						if ($.browser.msie || $.browser.safari) {
							command = "backcolor";
						} else {
							command = "hilitecolor";
						}
	
						if ($.browser.msie) {
							node = this.getInternalRange().parentElement();
						} else {
							selection = this.getInternalSelection();
							node = selection.extentNode || selection.focusNode;
	
							while (node.style === undefined) {
								node = node.parentNode;
								if (node.tagName && node.tagName.toLowerCase() === "body") {
									return;
								}
							}
						}
	
						if (node.style.backgroundColor === "rgb(255, 255, 102)" ||
								node.style.backgroundColor === "#ffff66") {
							args = "#ffffff";
						} else {
							args = "#ffff66";
						}
	
						this.editorDoc.execCommand(command, false, args);
					}
				},
	
				html: {
					groupIndex: 10,
					visible: false,
					exec: function () {
						var elementHeight;
	
						if (this.options.resizeOptions && $.fn.resizable) {
							elementHeight = this.element.height();
						}
	
						if (this.viewHTML) {
							this.setContent(this.original.value);
	
							$(this.original).hide();
							this.editor.show();
	
							if (this.options.resizeOptions && $.fn.resizable) {
								// if element.height still the same after frame was shown
								if (elementHeight === this.element.height()) {
									this.element.height(elementHeight + this.editor.height());
								}
	
								this.element.resizable($.extend(true, {
									alsoResize: this.editor
								}, this.options.resizeOptions));
							}
							
							this.ui.toolbar.find("li").each(function () {
								var li = $(this);
	
								if (li.hasClass("html")) {
									li.removeClass("active");
								} else {
									li.removeClass('disabled');
								}
							});
						} else {
							this.saveContent();
	
							$(this.original).css({
								width:	this.element.outerWidth() - 6,
								height: this.element.height() - this.ui.toolbar.height() - 6,
								resize: "none"
							}).show();
							this.editor.hide();
							
							if (this.options.resizeOptions && $.fn.resizable) {
								// if element.height still the same after frame was hidden
								if (elementHeight === this.element.height()) {
									this.element.height(this.ui.toolbar.height());
								}
	
								this.element.resizable("destroy");
							}
	
							this.ui.toolbar.find("li").each(function () {
								var li = $(this);
	
								if (li.hasClass("html")) {
									li.addClass("active");
								} else {
									if (false === li.hasClass("fullscreen")) {
										li.removeClass("active").addClass('disabled');
									}
								}
							});
						}
	
						this.viewHTML = !(this.viewHTML);
					},
					tooltip: "View source code"
				},
	
				increaseFontSize: {
					groupIndex: 9,
					visible: false,
					tags: ["big"],
					tooltip: "Increase font size",
					exec: function () {
						this.increaseFontSize();
					}
				},
	
				insertImage: {
					groupIndex: 6,
					visible: false,
					exec: function () {
						var self = this;
	
						if ($.wysiwyg.controls && $.wysiwyg.controls.image) {
							$.wysiwyg.controls.image.init(this);
						} else if ($.wysiwyg.autoload) {
							$.wysiwyg.autoload.control("wysiwyg.image.js", function () {
								self.controls.insertImage.exec.apply(self);
							});
						} else {
							console.error("$.wysiwyg.controls.image not defined. You need to include wysiwyg.image.js file");
						}
					},
					tags: ["img"],
					tooltip: "Insert image"
				},
	
				insertOrderedList: {
					groupIndex: 5,
					visible: false,
					tags: ["ol"],
					tooltip: "Insert Ordered List"
				},
	
				insertTable: {
					groupIndex: 6,
					visible: false,
					exec: function () {
						var self = this;
	
						if ($.wysiwyg.controls && $.wysiwyg.controls.table) {
							$.wysiwyg.controls.table(this);
						} else if ($.wysiwyg.autoload) {
							$.wysiwyg.autoload.control("wysiwyg.table.js", function () {
								self.controls.insertTable.exec.apply(self);
							});
						} else {
							console.error("$.wysiwyg.controls.table not defined. You need to include wysiwyg.table.js file");
						}
					},
					tags: ["table"],
					tooltip: "Insert table"
				},
	
				insertUnorderedList: {
					groupIndex: 5,
					visible: false,
					tags: ["ul"],
					tooltip: "Insert Unordered List"
				},
	
				italic: {
					groupIndex: 0,
					visible: false,
					tags: ["i", "em"],
					css: {
						fontStyle: "italic"
					},
					tooltip: "Italic",
					hotkey: {"ctrl": 1, "key": 73}
				},
	
				justifyLeft: {
					visible: false,
					groupIndex: 1,
					css: {
						textAlign: "left"
					},
					tooltip: "Justify Left"
				},
	
				justifyCenter: {
					groupIndex: 1,
					visible: false,
					tags: ["center"],
					css: {
						textAlign: "center"
					},
					tooltip: "Justify Center"
				},
	
				justifyRight: {
					groupIndex: 1,
					visible: false,
					css: {
						textAlign: "right"
					},
					tooltip: "Justify Right"
				},
	
				justifyFull: {
					groupIndex: 1,
					visible: false,
					css: {
						textAlign: "justify"
					},
					tooltip: "Justify Full"
				},
	
				ltr: {
					groupIndex: 9,
					visible: false,
					exec: function () {
						var p = this.dom.getElement("p");
	
						if (!p) {
							return false;
						}
	
						$(p).attr("dir", "ltr");
						return true;
					},
					tooltip : "Left to Right"
				},
	
				rtl: {
					groupIndex: 9,
					visible: false,
					exec: function () {
						var p = this.dom.getElement("p");
	
						if (!p) {
							return false;
						}
	
						$(p).attr("dir", "rtl");
						return true;
					},
					tooltip : "Right to Left"
				},
				
				indent: {
					groupIndex: 2,
					visible: false,
					tooltip: "Indent"
				},
	
				outdent: {
					groupIndex: 2,
					visible: false,
					tooltip: "Outdent"
				},
	
				insertHorizontalRule: {
					groupIndex: 5,
					visible: false,
					tags: ["hr"],
					tooltip: "Insert Horizontal Rule"
				},
	
				paragraph: {
					groupIndex: 7,
					visible: false,
					className: "paragraph",
					command: "FormatBlock",
					"arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<p>" : "p",
					tags: ["p"],
					tooltip: "Paragraph"
				},
	
				paste: {
					groupIndex: 8,
					visible: false,
					tooltip: "Paste"
				},
	
				undo: {
					groupIndex: 4,
					visible: false,
					tooltip: "Undo"
				},
	
				redo: {
					groupIndex: 4,
					visible: false,
					tooltip: "Redo"
				},
	
				removeFormat: {
					groupIndex: 10,
					visible: false,
					exec: function () {
						this.removeFormat();
					},
					tooltip: "Remove formatting"
				},
	
	
				underline: {
					groupIndex: 0,
					visible: false,
					tags: ["u"],
					css: {
						textDecoration: "underline"
					},
					tooltip: "Underline",
					hotkey: {"ctrl": 1, "key": 85}
				},
	
				strikeThrough: {
					groupIndex: 0,
					visible: false,
					tags: ["s", "strike"],
					css: {
						textDecoration: "line-through"
					},
					tooltip: "Strike-through"
				},
	
				subscript: {
					groupIndex: 3,
					visible: false,
					tags: ["sub"],
					tooltip: "Subscript"
				},
	
				superscript: {
					groupIndex: 3,
					visible: false,
					tags: ["sup"],
					tooltip: "Superscript"
				},
	
				code: {
					visible : false,
					groupIndex: 6,
					tooltip: "Code snippet",
					exec: function () {
						var range	= this.getInternalRange(),
							common	= $(range.commonAncestorContainer),
							$nodeName = range.commonAncestorContainer.nodeName.toLowerCase();
						if (common.parent("code").length) {
							common.unwrap();
						} else {
							if ($nodeName !== "body") {
								common.wrap("<code/>");
							}
						}
					}
				},
				
				cssWrap: {
					visible : false,
					groupIndex: 6,
					tooltip: "CSS Wrapper",
					exec: function () { 
						$.wysiwyg.controls.cssWrap.init(this);
					}
				}
				
			};
	
			this.defaults = {
				html: '<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>INITIAL_CONTENT</body></html>',
				debug: false,
				controls: {},
				css: {},
				events: {},
				autoGrow: false,
				autoSave: true,
				brIE: true,					// http://code.google.com/p/jwysiwyg/issues/detail?id=15
				formHeight: 270,
				formWidth: 440,
				iFrameClass: null,
				initialContent: "<p>Initial content</p>",
				maxHeight: 10000,			// see autoGrow
				maxLength: 0,
				messages: {
					nonSelection: "Select the text you wish to link"
				},
				toolbarHtml: '<ul role="menu" class="toolbar"></ul>',
				removeHeadings: false,
				replaceDivWithP: false,
				resizeOptions: false,
				rmUnusedControls: false,	// https://github.com/akzhan/jwysiwyg/issues/52
				rmUnwantedBr: true,			// http://code.google.com/p/jwysiwyg/issues/detail?id=11
				tableFiller: "Lorem ipsum",
				initialMinHeight: null,
	
				controlImage: {
					forceRelativeUrls: false
				},
	
				controlLink: {
					forceRelativeUrls: false
				},
	
				plugins: { // placeholder for plugins settings
					autoload: false,
					i18n: false,
					rmFormat: {
						rmMsWordMarkup: false
					}
				}
			};
	
			this.availableControlProperties = [
				"arguments",
				"callback",
				"className",
				"command",
				"css",
				"custom",
				"exec",
				"groupIndex",
				"hotkey",
				"icon",
				"tags",
				"tooltip",
				"visible"
			];
	
			this.editor			= null;
			this.editorDoc		= null;
			this.element		= null;
			this.options		= {};
			this.original		= null;
			this.savedRange		= null;
			this.timers			= [];
			this.validKeyCodes	= [8, 9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46];
	
			this.isDestroyed	= false;
	
			this.dom		= { // DOM related properties and methods
				ie:		{
					parent: null // link to dom
				},
				w3c:	{
					parent: null // link to dom
				}
			};
			this.dom.parent		= this;
			this.dom.ie.parent	= this.dom;
			this.dom.w3c.parent	= this.dom;
	
			this.ui			= {};	// UI related properties and methods
			this.ui.self	= this;
			this.ui.toolbar	= null;
			this.ui.initialHeight = null; // ui.grow
	
			this.dom.getAncestor = function (element, filterTagName) {
				filterTagName = filterTagName.toLowerCase();
	
				while (element && "body" !== element.tagName.toLowerCase()) {
					if (filterTagName === element.tagName.toLowerCase()) {
						return element;
					}
	
					element = element.parentNode;
				}
	
				return null;
			};
	
			this.dom.getElement = function (filterTagName) {
				var dom = this;
	
				if (window.getSelection) {
					return dom.w3c.getElement(filterTagName);
				} else {
					return dom.ie.getElement(filterTagName);
				}
			};
	
			this.dom.ie.getElement = function (filterTagName) {
				var dom			= this.parent,
					selection	= dom.parent.getInternalSelection(),
					range		= selection.createRange(),
					element;
	
				if ("Control" === selection.type) {
					// control selection
					if (1 === range.length) {
						element = range.item(0);
					} else {
						// multiple control selection
						return null;
					}
				} else {
					element = range.parentElement();
				}
	
				return dom.getAncestor(element, filterTagName);
			};
	
			this.dom.w3c.getElement = function (filterTagName) {
				var dom		= this.parent,
					range	= dom.parent.getInternalRange(),
					element;
	
				if (!range) {
					return null;
				}
	
				element	= range.commonAncestorContainer;
	
				if (3 === element.nodeType) {
					element = element.parentNode;
				}
	
				// if startContainer not Text, Comment, or CDATASection element then
				// startOffset is the number of child nodes between the start of the
				// startContainer and the boundary point of the Range
				if (element === range.startContainer) {
					element = element.childNodes[range.startOffset];
				}
	
				return dom.getAncestor(element, filterTagName);
			};
	
			this.ui.addHoverClass = function () {
				$(this).addClass("wysiwyg-button-hover");
			};
	
			this.ui.appendControls = function () {
				var ui = this,
					self = this.self,
					controls = self.parseControls(),
					hasVisibleControls	= true, // to prevent separator before first item
					groups = [],
					controlsByGroup = {},
					i,
					currentGroupIndex, // jslint wants all vars at top of function
					iterateGroup = function (controlName, control) {
						if (control.groupIndex && currentGroupIndex !== control.groupIndex) {
							currentGroupIndex = control.groupIndex;
							hasVisibleControls = false;
						}
	
						if (!control.visible) {
							return;
						}
	
						if (!hasVisibleControls) {
							ui.appendItemSeparator();
							hasVisibleControls = true;
						}
	
						if (control.custom) {
							ui.appendItemCustom(controlName, control);
						} else {
							ui.appendItem(controlName, control);
						}
					};
	
				$.each(controls, function (name, c) {
					var index = "empty";
	
					if (undefined !== c.groupIndex) {
						if ("" === c.groupIndex) {
							index = "empty";
						} else {
							index = c.groupIndex;
						}
					}
	
					if (undefined === controlsByGroup[index]) {
						groups.push(index);
						controlsByGroup[index] = {};
					}
					controlsByGroup[index][name] = c;
				});
	
				groups.sort(function (a, b) {
					if ("number" === typeof (a) && typeof (a) === typeof (b)) {
						return (a - b);
					} else {
						a = a.toString();
						b = b.toString();
	
						if (a > b) {
							return 1;
						}
	
						if (a === b) {
							return 0;
						}
	
						return -1;
					}
				});
	
				if (0 < groups.length) {
					// set to first index in groups to proper placement of separator
					currentGroupIndex = groups[0];
				}
	
				for (i = 0; i < groups.length; i += 1) {
					$.each(controlsByGroup[groups[i]], iterateGroup);
				}
			};
	
			this.ui.appendItem = function (name, control) {
				var self = this.self,
					className = control.className || control.command || name || "empty",
					tooltip = control.tooltip || control.command || name || "";
	
				return $('<li role="menuitem" unselectable="on">' + (className) + "</li>")
					.addClass(className)
					.attr("title", tooltip)
					.hover(this.addHoverClass, this.removeHoverClass)
					.click(function () {
						if ($(this).hasClass("disabled")) {
							return false;
						}
	
						self.triggerControl.apply(self, [name, control]);
	
						this.blur();
						self.ui.returnRange();
						self.ui.focus();
						return true;
					})
					.appendTo(self.ui.toolbar);
			};
	
			this.ui.appendItemCustom = function (name, control) {
				var self = this.self,
					tooltip = control.tooltip || control.command || name || "";
	
				if (control.callback) {
					$(window).bind("trigger-" + name + ".wysiwyg", control.callback);
				}
	
				return $('<li role="menuitem" unselectable="on" style="background: url(\'' + control.icon + '\') no-repeat;"></li>')
					.addClass("custom-command-" + name)
					.addClass("wysiwyg-custom-command")
					.addClass(name)
					.attr("title", tooltip)
					.hover(this.addHoverClass, this.removeHoverClass)
					.click(function () {
						if ($(this).hasClass("disabled")) {
							return false;
						}
	
						self.triggerControl.apply(self, [name, control]);
	
						this.blur();
						self.ui.returnRange();
						self.ui.focus();
	
						self.triggerControlCallback(name);
						return true;
					})
					.appendTo(self.ui.toolbar);
			};
	
			this.ui.appendItemSeparator = function () {
				var self = this.self;
				return $('<li role="separator" class="separator"></li>').appendTo(self.ui.toolbar);
			};
	
			this.autoSaveFunction = function () {
				this.saveContent();
			};
	
			this.ui.checkTargets = function (element) {
				var self = this.self;
	
				$.each(self.options.controls, function (name, control) {
					var className = control.className || control.command || name || "empty",
						tags,
						elm,
						css,
						el,
						checkActiveStatus = function (cssProperty, cssValue) {
							var handler;
	
							if ("function" === typeof (cssValue)) {
								handler = cssValue;
								if (handler(el.css(cssProperty).toString().toLowerCase(), self)) {
									self.ui.toolbar.find("." + className).addClass("active");
								}
							} else {
								if (el.css(cssProperty).toString().toLowerCase() === cssValue) {
									self.ui.toolbar.find("." + className).addClass("active");
								}
							}
						};
	
					if ("fullscreen" !== className) {
						self.ui.toolbar.find("." + className).removeClass("active");
					}
	
					if (control.tags || (control.options && control.options.tags)) {
						tags = control.tags || (control.options && control.options.tags);
	
						elm = element;
						while (elm) {
							if (elm.nodeType !== 1) {
								break;
							}
	
							if ($.inArray(elm.tagName.toLowerCase(), tags) !== -1) {
								self.ui.toolbar.find("." + className).addClass("active");
							}
	
							elm = elm.parentNode;
						}
					}
	
					if (control.css || (control.options && control.options.css)) {
						css = control.css || (control.options && control.options.css);
						el = $(element);
	
						while (el) {
							if (el[0].nodeType !== 1) {
								break;
							}
							$.each(css, checkActiveStatus);
	
							el = el.parent();
						}
					}
				});
			};
	
			this.ui.designMode = function () {
				var attempts = 3,
					self = this.self,
					runner;
					runner = function (attempts) {
						if ("on" === self.editorDoc.designMode) {
							if (self.timers.designMode) {
								window.clearTimeout(self.timers.designMode);
							}
	
							// IE needs to reget the document element (this.editorDoc) after designMode was set
							if (self.innerDocument() !== self.editorDoc) {
								self.ui.initFrame();
							}
	
							return;
						}
	
						try {
							self.editorDoc.designMode = "on";
						} catch (e) {
						}
	
						attempts -= 1;
						if (attempts > 0) {
							self.timers.designMode = window.setTimeout(function () { runner(attempts); }, 100);
						}
					};
	
				runner(attempts);
			};
	
			this.destroy = function () {
				this.isDestroyed = true;
	
				var i, $form = this.element.closest("form");
	
				for (i = 0; i < this.timers.length; i += 1) {
					window.clearTimeout(this.timers[i]);
				}
	
				// Remove bindings
				$form.unbind(".wysiwyg");
				this.element.remove();
				$.removeData(this.original, "wysiwyg");
				$(this.original).show();
				return this;
			};
	
			this.getRangeText = function () {
				var r = this.getInternalRange();
	
				if (r.toString) {
					r = r.toString();
				} else if (r.text) {	// IE
					r = r.text;
				}
	
				return r;
			};
			//not used?
			this.execute = function (command, arg) {
				if (typeof (arg) === "undefined") {
					arg = null;
				}
				this.editorDoc.execCommand(command, false, arg);
			};
	
			this.extendOptions = function (options) {
				var controls = {};
	
				/**
				 * If the user set custom controls, we catch it, and merge with the
				 * defaults controls later.
				 */
				if ("object" === typeof options.controls) {
					controls = options.controls;
					delete options.controls;
				}
	
				options = $.extend(true, {}, this.defaults, options);
				options.controls = $.extend(true, {}, controls, this.controls, controls);
	
				if (options.rmUnusedControls) {
					$.each(options.controls, function (controlName) {
						if (!controls[controlName]) {
							delete options.controls[controlName];
						}
					});
				}
	
				return options;
			};
	
			this.ui.focus = function () {
				var self = this.self;
	
				self.editor.get(0).contentWindow.focus();
				return self;
			};
	
			this.ui.returnRange = function () {
				var self = this.self, sel;
	
				if (self.savedRange !== null) {
					if (window.getSelection) { //non IE and there is already a selection
						sel = window.getSelection();
						if (sel.rangeCount > 0) {
							sel.removeAllRanges();
						}
						try {
							sel.addRange(self.savedRange);
						} catch (e) {
							console.error(e);
						}
					} else if (window.document.createRange) { // non IE and no selection
						window.getSelection().addRange(self.savedRange);
					} else if (window.document.selection) { //IE
						self.savedRange.select();
					}
	
					self.savedRange = null;
				}
			};
	
			this.increaseFontSize = function () {
				if ($.browser.mozilla || $.browser.opera) {
					this.editorDoc.execCommand('increaseFontSize', false, null);
				} else if ($.browser.safari) {
					var newNode = this.editorDoc.createElement('big');
					this.getInternalRange().surroundContents(newNode);
				} else {
					console.error("Internet Explorer?");
				}
			};
	
			this.decreaseFontSize = function () {
				if ($.browser.mozilla || $.browser.opera) {
					this.editorDoc.execCommand('decreaseFontSize', false, null);
				} else if ($.browser.safari) {
					var newNode = this.editorDoc.createElement('small');
					this.getInternalRange().surroundContents(newNode);
				} else {
					console.error("Internet Explorer?");
				}
			};
	
			this.getContent = function () {
				if (this.viewHTML) {
					this.setContent(this.original.value);
				}
				return this.events.filter('getContent', this.editorDoc.body.innerHTML);
			};
			
			/**
			 * A jWysiwyg specific event system.
			 *
			 * Example:
			 * 
			 * $("#editor").getWysiwyg().events.bind("getContent", function (orig) {
			 *     return "<div id='content'>"+orgi+"</div>";
			 * });
			 * 
			 * This makes it so that when ever getContent is called, it is wrapped in a div#content.
			 */
			this.events = {
				_events : {},
				
				/**
				 * Similar to jQuery's bind, but for jWysiwyg only.
				 */
				bind : function (eventName, callback) {
					if (typeof (this._events.eventName) !== "object") {
						this._events[eventName] = [];
					}
					this._events[eventName].push(callback);
				},
				
				/**
				 * Similar to jQuery's trigger, but for jWysiwyg only.
				 */
				trigger : function (eventName, args) {
					if (typeof (this._events.eventName) === "object") {
						var editor = this.editor;
						$.each(this._events[eventName], function (k, v) {
							if (typeof (v) === "function") {
								v.apply(editor, args);
							}
						});
					}
				},
				
				/**
				 * This "filters" `originalText` by passing it as the first argument to every callback
				 * with the name `eventName` and taking the return value and passing it to the next function.
				 *
				 * This function returns the result after all the callbacks have been applied to `originalText`.
				 */
				filter : function (eventName, originalText) {
					if (typeof (this._events[eventName]) === "object") {
						var editor = this.editor,
							args = Array.prototype.slice.call(arguments, 1);
	
						$.each(this._events[eventName], function (k, v) {
							if (typeof (v) === "function") {
								originalText = v.apply(editor, args);
							}
						});
					}
					return originalText;
				}
			};
	
			this.getElementByAttributeValue = function (tagName, attributeName, attributeValue) {
				var i, value, elements = this.editorDoc.getElementsByTagName(tagName);
	
				for (i = 0; i < elements.length; i += 1) {
					value = elements[i].getAttribute(attributeName);
	
					if ($.browser.msie) {
						/** IE add full path, so I check by the last chars. */
						value = value.substr(value.length - attributeValue.length);
					}
	
					if (value === attributeValue) {
						return elements[i];
					}
				}
	
				return false;
			};
	
			this.getInternalRange = function () {
				var selection = this.getInternalSelection();
	
				if (!selection) {
					return null;
				}
	
				if (selection.rangeCount && selection.rangeCount > 0) { // w3c
					return selection.getRangeAt(0);
				} else if (selection.createRange) { // ie
					return selection.createRange();
				}
	
				return null;
			};
	
			this.getInternalSelection = function () {
				// firefox: document.getSelection is deprecated
				if (this.editor.get(0).contentWindow) {
					if (this.editor.get(0).contentWindow.getSelection) {
						return this.editor.get(0).contentWindow.getSelection();
					}
					if (this.editor.get(0).contentWindow.selection) {
						return this.editor.get(0).contentWindow.selection;
					}
				}
				if (this.editorDoc.getSelection) {
					return this.editorDoc.getSelection();
				}
				if (this.editorDoc.selection) {
					return this.editorDoc.selection;
				}
	
				return null;
			};
	
			this.getRange = function () {
				var selection = this.getSelection();
	
				if (!selection) {
					return null;
				}
	
				if (selection.rangeCount && selection.rangeCount > 0) { // w3c
					selection.getRangeAt(0);
				} else if (selection.createRange) { // ie
					return selection.createRange();
				}
	
				return null;
			};
	
			this.getSelection = function () {
				return (window.getSelection) ? window.getSelection() : window.document.selection;
			};
	
			// :TODO: you can type long string and letters will be hidden because of overflow
			this.ui.grow = function () {
				var self = this.self,
					innerBody = $(self.editorDoc.body),
					innerHeight = $.browser.msie ? innerBody[0].scrollHeight : innerBody.height() + 2 + 20, // 2 - borders, 20 - to prevent content jumping on grow
					minHeight = self.ui.initialHeight,
					height = Math.max(innerHeight, minHeight);
	
				height = Math.min(height, self.options.maxHeight);
	
				self.editor.attr("scrolling", height < self.options.maxHeight ? "no" : "auto"); // hide scrollbar firefox
				innerBody.css("overflow", height < self.options.maxHeight ? "hidden" : ""); // hide scrollbar chrome
	
				self.editor.get(0).height = height;
	
				return self;
			};
	
			this.init = function (element, options) {
				var self = this,
					$form = $(element).closest("form"),
					newX = element.width || element.clientWidth || 0,
					newY = element.height || element.clientHeight || 0
					;
	
				this.options	= this.extendOptions(options);
				this.original	= element;
				this.ui.toolbar	= $(this.options.toolbarHtml);
	
				if ($.browser.msie && parseInt($.browser.version, 10) < 8) {
					this.options.autoGrow = false;
				}
	
				if (newX === 0 && element.cols) {
					newX = (element.cols * 8) + 21;
				}
				if (newY === 0 && element.rows) {
					newY = (element.rows * 16) + 16;
				}
	
				this.editor = $(window.location.protocol === "https:" ? '<iframe src="javascript:false;"></iframe>' : "<iframe></iframe>").attr("frameborder", "0");
	
				if (this.options.iFrameClass) {
					this.editor.addClass(this.options.iFrameClass);
				} else {
					this.editor.css({
						minHeight: (newY - 6).toString() + "px",
						// fix for issue 12 ( http://github.com/akzhan/jwysiwyg/issues/issue/12 )
						width: (newX > 50) ? (newX - 8).toString() + "px" : ""
					});
					if ($.browser.msie && parseInt($.browser.version, 10) < 7) {
						this.editor.css("height", newY.toString() + "px");
					}
				}
				/**
				 * http://code.google.com/p/jwysiwyg/issues/detail?id=96
				 */
				this.editor.attr("tabindex", $(element).attr("tabindex"));
	
				this.element = $("<div/>").addClass("wysiwyg");
	
				if (!this.options.iFrameClass) {
					this.element.css({
						width: (newX > 0) ? newX.toString() + "px" : "100%"
					});
				}
	
				$(element).hide().before(this.element);
	
				this.viewHTML = false;
	
				/**
				 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52
				 */
				this.initialContent = $(element).val();
				this.ui.initFrame();
	
				if (this.options.resizeOptions && $.fn.resizable) {
					this.element.resizable($.extend(true, {
						alsoResize: this.editor
					}, this.options.resizeOptions));
				}
	
				if (this.options.autoSave) {
					$form.bind("submit.wysiwyg", function () { self.autoSaveFunction(); });
				}
	
				$form.bind("reset.wysiwyg", function () { self.resetFunction(); });
			};
	
			this.ui.initFrame = function () {
				var self = this.self,
					stylesheet,
					growHandler,
					saveHandler;
	
				self.ui.appendControls();
				self.element.append(self.ui.toolbar)
					.append($("<div><!-- --></div>")
						.css({
							clear: "both"
						}))
					.append(self.editor);
	
				self.editorDoc = self.innerDocument();
	
				if (self.isDestroyed) {
					return null;
				}
	
				self.ui.designMode();
				self.editorDoc.open();
				self.editorDoc.write(
					self.options.html
						/**
						 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=144
						 */
						.replace(/INITIAL_CONTENT/, function () { return self.wrapInitialContent(); })
				);
				self.editorDoc.close();
	
				$.wysiwyg.plugin.bind(self);
	
				$(self.editorDoc).trigger("initFrame.wysiwyg");
	
				$(self.editorDoc).bind("click.wysiwyg", function (event) {
					self.ui.checkTargets(event.target ? event.target : event.srcElement);
				});
	
				/**
				 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20
				 */
				$(self.original).focus(function () {
					if ($(this).filter(":visible")) {
						return;
					}
					self.ui.focus();
				});
	
				$(self.editorDoc).keydown(function (event) {
					var emptyContentRegex;
					if (event.keyCode === 8) { // backspace
						emptyContentRegex = /^<([\w]+)[^>]*>(<br\/?>)?<\/\1>$/;
						if (emptyContentRegex.test(self.getContent())) { // if content is empty
							event.stopPropagation(); // prevent remove single empty tag
							return false;
						}
					}
					return true;
				});
	
				if (!$.browser.msie) {
					$(self.editorDoc).keydown(function (event) {
						var controlName;
	
						/* Meta for Macs. tom@punkave.com */
						if (event.ctrlKey || event.metaKey) {
							for (controlName in self.controls) {
								if (self.controls[controlName].hotkey && self.controls[controlName].hotkey.ctrl) {
									if (event.keyCode === self.controls[controlName].hotkey.key) {
										self.triggerControl.apply(self, [controlName, self.controls[controlName]]);
	
										return false;
									}
								}
							}
						}
	
						return true;
					});
				} else if (self.options.brIE) {
					$(self.editorDoc).keydown(function (event) {
						if (event.keyCode === 13) {
							var rng = self.getRange();
							rng.pasteHTML("<br/>");
							rng.collapse(false);
							rng.select();
	
							return false;
						}
	
						return true;
					});
				}
	
				if (self.options.plugins.rmFormat.rmMsWordMarkup) {
					$(self.editorDoc).bind("keyup.wysiwyg", function (event) {
						if (event.ctrlKey || event.metaKey) {
							// CTRL + V (paste)
							if (86 === event.keyCode) {
								if ($.wysiwyg.rmFormat) {
									if ("object" === typeof (self.options.plugins.rmFormat.rmMsWordMarkup)) {
										$.wysiwyg.rmFormat.run(self, {rules: { msWordMarkup: self.options.plugins.rmFormat.rmMsWordMarkup }});
									} else {
										$.wysiwyg.rmFormat.run(self, {rules: { msWordMarkup: { enabled: true }}});
									}
								}
							}
						}
					});
				}
	
				if (self.options.autoSave) {
					$(self.editorDoc).keydown(function () { self.autoSaveFunction(); })
						.keyup(function () { self.autoSaveFunction(); })
						.mousedown(function () { self.autoSaveFunction(); })
						.bind($.support.noCloneEvent ? "input.wysiwyg" : "paste.wysiwyg", function () { self.autoSaveFunction(); });
				}
	
				if (self.options.autoGrow) {
					if (self.options.initialMinHeight !== null) {
						self.ui.initialHeight = self.options.initialMinHeight;
					} else {
						self.ui.initialHeight = $(self.editorDoc).height();
					}
					$(self.editorDoc.body).css("border", "1px solid white"); // cancel margin collapsing
	
					growHandler = function () {
						self.ui.grow();
					};
	
					$(self.editorDoc).keyup(growHandler);
					$(self.editorDoc).bind("editorRefresh.wysiwyg", growHandler);
	
					// fix when content height > textarea height
					self.ui.grow();
				}
	
				if (self.options.css) {
					if (String === self.options.css.constructor) {
						if ($.browser.msie) {
							stylesheet = self.editorDoc.createStyleSheet(self.options.css);
							$(stylesheet).attr({
								"media":	"all"
							});
						} else {
							stylesheet = $("<link/>").attr({
								"href":		self.options.css,
								"media":	"all",
								"rel":		"stylesheet",
								"type":		"text/css"
							});
	
							$(self.editorDoc).find("head").append(stylesheet);
						}
					} else {
						self.timers.initFrame_Css = window.setTimeout(function () {
							$(self.editorDoc.body).css(self.options.css);
						}, 0);
					}
				}
	
				if (self.initialContent.length === 0) {
					if ("function" === typeof (self.options.initialContent)) {
						self.setContent(self.options.initialContent());
					} else {
						self.setContent(self.options.initialContent);
					}
				}
	
				if (self.options.maxLength > 0) {
					$(self.editorDoc).keydown(function (event) {
						if ($(self.editorDoc).text().length >= self.options.maxLength && $.inArray(event.which, self.validKeyCodes) === -1) {
							event.preventDefault();
						}
					});
				}
				
				// Support event callbacks
				$.each(self.options.events, function (key, handler) {
					$(self.editorDoc).bind(key + ".wysiwyg", function (event) {
						// Trigger event handler, providing the event and api to 
						// support additional functionality.
						handler.apply(self.editorDoc, [event, self]);
					});
				});
	
				// restores selection properly on focus
				if ($.browser.msie) {
					// Event chain: beforedeactivate => focusout => blur.
					// Focusout & blur fired too late to handle internalRange() in dialogs.
					// When clicked on input boxes both got range = null
					$(self.editorDoc).bind("beforedeactivate.wysiwyg", function () {
						self.savedRange = self.getInternalRange();
					});
				} else {
					$(self.editorDoc).bind("blur.wysiwyg", function () {
						self.savedRange = self.getInternalRange();
					});
				}
	
				$(self.editorDoc.body).addClass("wysiwyg");
				if (self.options.events && self.options.events.save) {
					saveHandler = self.options.events.save;
	
					$(self.editorDoc).bind("keyup.wysiwyg", saveHandler);
					$(self.editorDoc).bind("change.wysiwyg", saveHandler);
	
					if ($.support.noCloneEvent) {
						$(self.editorDoc).bind("input.wysiwyg", saveHandler);
					} else {
						$(self.editorDoc).bind("paste.wysiwyg", saveHandler);
						$(self.editorDoc).bind("cut.wysiwyg", saveHandler);
					}
				}
				
				/**
				 * XHTML5 {@link https://github.com/akzhan/jwysiwyg/issues/152}
				 */
				if (self.options.xhtml5 && self.options.unicode) {
					var replacements = {ne:8800,le:8804,para:182,xi:958,darr:8595,nu:957,oacute:243,Uacute:218,omega:969,prime:8242,pound:163,igrave:236,thorn:254,forall:8704,emsp:8195,lowast:8727,brvbar:166,alefsym:8501,nbsp:160,delta:948,clubs:9827,lArr:8656,Omega:937,Auml:196,cedil:184,and:8743,plusmn:177,ge:8805,raquo:187,uml:168,equiv:8801,laquo:171,rdquo:8221,Epsilon:917,divide:247,fnof:402,chi:967,Dagger:8225,iacute:237,rceil:8969,sigma:963,Oslash:216,acute:180,frac34:190,lrm:8206,upsih:978,Scaron:352,part:8706,exist:8707,nabla:8711,image:8465,prop:8733,zwj:8205,omicron:959,aacute:225,Yuml:376,Yacute:221,weierp:8472,rsquo:8217,otimes:8855,kappa:954,thetasym:977,harr:8596,Ouml:214,Iota:921,ograve:242,sdot:8901,copy:169,oplus:8853,acirc:226,sup:8835,zeta:950,Iacute:205,Oacute:211,crarr:8629,Nu:925,bdquo:8222,lsquo:8216,apos:39,Beta:914,eacute:233,egrave:232,lceil:8968,Kappa:922,piv:982,Ccedil:199,ldquo:8220,Xi:926,cent:162,uarr:8593,hellip:8230,Aacute:193,ensp:8194,sect:167,Ugrave:217,aelig:230,ordf:170,curren:164,sbquo:8218,macr:175,Phi:934,Eta:919,rho:961,Omicron:927,sup2:178,euro:8364,aring:229,Theta:920,mdash:8212,uuml:252,otilde:245,eta:951,uacute:250,rArr:8658,nsub:8836,agrave:224,notin:8713,ndash:8211,Psi:936,Ocirc:212,sube:8838,szlig:223,micro:181,not:172,sup1:185,middot:183,iota:953,ecirc:234,lsaquo:8249,thinsp:8201,sum:8721,ntilde:241,scaron:353,cap:8745,atilde:227,lang:10216,__replacement:65533,isin:8712,gamma:947,Euml:203,ang:8736,upsilon:965,Ntilde:209,hearts:9829,Alpha:913,Tau:932,spades:9824,dagger:8224,THORN:222,"int":8747,lambda:955,Eacute:201,Uuml:220,infin:8734,rlm:8207,Aring:197,ugrave:249,Egrave:200,Acirc:194,rsaquo:8250,ETH:208,oslash:248,alpha:945,Ograve:210,Prime:8243,mu:956,ni:8715,real:8476,bull:8226,beta:946,icirc:238,eth:240,prod:8719,larr:8592,ordm:186,perp:8869,Gamma:915,reg:174,ucirc:251,Pi:928,psi:968,tilde:732,asymp:8776,zwnj:8204,Agrave:192,deg:176,AElig:198,times:215,Delta:916,sim:8764,Otilde:213,Mu:924,uArr:8657,circ:710,theta:952,Rho:929,sup3:179,diams:9830,tau:964,Chi:935,frac14:188,oelig:339,shy:173,or:8744,dArr:8659,phi:966,iuml:239,Lambda:923,rfloor:8971,iexcl:161,cong:8773,ccedil:231,Icirc:206,frac12:189,loz:9674,rarr:8594,cup:8746,radic:8730,frasl:8260,euml:235,OElig:338,hArr:8660,Atilde:195,Upsilon:933,there4:8756,ouml:246,oline:8254,Ecirc:202,yacute:253,auml:228,permil:8240,sigmaf:962,iquest:191,empty:8709,pi:960,Ucirc:219,supe:8839,Igrave:204,yen:165,rang:10217,trade:8482,lfloor:8970,minus:8722,Zeta:918,sub:8834,epsilon:949,yuml:255,Sigma:931,Iuml:207,ocirc:244};
					self.events.bind("getContent", function (text) {
						return text.replace(/&(?:amp;)?(?!amp|lt|gt|quot)([a-z][a-z0-9]*);/gi, function (str, p1) {
							if (!replacements[p1]) {
								p1 = p1.toLowerCase();
								if (!replacements[p1]) {
									p1 = "__replacement";
								}
							}
							
							var num = replacements[p1];
							/* Numeric return if ever wanted: return replacements[p1] ? "&#"+num+";" : ""; */
							return String.fromCharCode(num);
						});
					});
				}
			};
	
			this.innerDocument = function () {
				var element = this.editor.get(0);
	
				if (element.nodeName.toLowerCase() === "iframe") {
					if (element.contentDocument) {				// Gecko
						return element.contentDocument;
					} else if (element.contentWindow) {			// IE
						return element.contentWindow.document;
					}
	
					if (this.isDestroyed) {
						return null;
					}
	
					console.error("Unexpected error in innerDocument");
	
					/*
					 return ( $.browser.msie )
					 ? document.frames[element.id].document
					 : element.contentWindow.document // contentDocument;
					 */
				}
	
				return element;
			};
	
			this.insertHtml = function (szHTML) {
				var img, range;
	
				if (!szHTML || szHTML.length === 0) {
					return this;
				}
	
				if ($.browser.msie) {
					this.ui.focus();
					this.editorDoc.execCommand("insertImage", false, "#jwysiwyg#");
					img = this.getElementByAttributeValue("img", "src", "#jwysiwyg#");
					if (img) {
						$(img).replaceWith(szHTML);
					}
				} else {
					if ($.browser.mozilla) { // @link https://github.com/akzhan/jwysiwyg/issues/50
						if (1 === $(szHTML).length) {
							range = this.getInternalRange();
							range.deleteContents();
							range.insertNode($(szHTML).get(0));
						} else {
							this.editorDoc.execCommand("insertHTML", false, szHTML);
						}
					} else {
						if (!this.editorDoc.execCommand("insertHTML", false, szHTML)) {
							this.editor.focus();
							/* :TODO: place caret at the end
							if (window.getSelection) {
							} else {
							}
							this.editor.focus();
							*/
							this.editorDoc.execCommand("insertHTML", false, szHTML);
						}
					}
				}
	
				this.saveContent();
				
				return this;
			};
	
			this.parseControls = function () {
				var self = this;
	
				$.each(this.options.controls, function (controlName, control) {
					$.each(control, function (propertyName) {
						if (-1 === $.inArray(propertyName, self.availableControlProperties)) {
							throw controlName + '["' + propertyName + '"]: property "' + propertyName + '" not exists in Wysiwyg.availableControlProperties';
						}
					});
				});
	
				if (this.options.parseControls) {
					return this.options.parseControls.call(this);
				}
	
				return this.options.controls;
			};
	
			this.removeFormat = function () {
				if ($.browser.msie) {
					this.ui.focus();
				}
	
				if (this.options.removeHeadings) {
					this.editorDoc.execCommand("formatBlock", false, "<p>"); // remove headings
				}
	
				this.editorDoc.execCommand("removeFormat", false, null);
				this.editorDoc.execCommand("unlink", false, null);
	
				if ($.wysiwyg.rmFormat && $.wysiwyg.rmFormat.enabled) {
					if ("object" === typeof (this.options.plugins.rmFormat.rmMsWordMarkup)) {
						$.wysiwyg.rmFormat.run(this, {rules: { msWordMarkup: this.options.plugins.rmFormat.rmMsWordMarkup }});
					} else {
						$.wysiwyg.rmFormat.run(this, {rules: { msWordMarkup: { enabled: true }}});
					}
				}
	
				return this;
			};
	
			this.ui.removeHoverClass = function () {
				$(this).removeClass("wysiwyg-button-hover");
			};
	
			this.resetFunction = function () {
				this.setContent(this.initialContent);
			};
	
			this.saveContent = function () {
				if (this.viewHTML)
				{
					return; // no need
				}
				if (this.original) {
					var content, newContent;
	
					content = this.getContent();
	
					if (this.options.rmUnwantedBr) {
						content = content.replace(/<br\/?>$/, "");
					}
	
					if (this.options.replaceDivWithP) {
						newContent = $("<div/>").addClass("temp").append(content);
	
						newContent.children("div").each(function () {
							var element = $(this), p = element.find("p"), i;
	
							if (0 === p.length) {
								p = $("<p></p>");
	
								if (this.attributes.length > 0) {
									for (i = 0; i < this.attributes.length; i += 1) {
										p.attr(this.attributes[i].name, element.attr(this.attributes[i].name));
									}
								}
	
								p.append(element.html());
	
								element.replaceWith(p);
							}
						});
						
						content = newContent.html();
					}
	
					$(this.original).val(content);
	
					if (this.options.events && this.options.events.save) {
						this.options.events.save.call(this);
					}
				}
	
				return this;
			};
	
			this.setContent = function (newContent) {
				this.editorDoc.body.innerHTML = newContent;
				this.saveContent();
	
				return this;
			};
	
			this.triggerControl = function (name, control) {
				var cmd = control.command || name,
					args = control["arguments"] || [];
	
				if (control.exec) {
					control.exec.apply(this);
				} else {
					this.ui.focus();
					this.ui.withoutCss();
					// when click <Cut>, <Copy> or <Paste> got "Access to XPConnect service denied" code: "1011"
					// in Firefox untrusted JavaScript is not allowed to access the clipboard
					try {
						this.editorDoc.execCommand(cmd, false, args);
					} catch (e) {
						console.error(e);
					}
				}
	
				if (this.options.autoSave) {
					this.autoSaveFunction();
				}
			};
	
			this.triggerControlCallback = function (name) {
				$(window).trigger("trigger-" + name + ".wysiwyg", [this]);
			};
	
			this.ui.withoutCss = function () {
				var self = this.self;
	
				if ($.browser.mozilla) {
					try {
						self.editorDoc.execCommand("styleWithCSS", false, false);
					} catch (e) {
						try {
							self.editorDoc.execCommand("useCSS", false, true);
						} catch (e2) {
						}
					}
				}
	
				return self;
			};
	
			this.wrapInitialContent = function () {
				var content = this.initialContent,
					found = content.match(/<\/?p>/gi);
	
				if (!found) {
					return "<p>" + content + "</p>";
				} else {
					// :TODO: checking/replacing
				}
	
				return content;
			};
		}
	
		/*
		 * Wysiwyg namespace: public properties and methods
		 */
		$.wysiwyg = {
			messages: {
				noObject: "Something goes wrong, check object"
			},
	
			/**
			 * Custom control support by Alec Gorge ( http://github.com/alecgorge )
			 */
			addControl: function (object, name, settings) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg"),
						customControl = {},
						toolbar;
	
					if (!oWysiwyg) {
						return this;
					}
	
					customControl[name] = $.extend(true, {visible: true, custom: true}, settings);
					$.extend(true, oWysiwyg.options.controls, customControl);
	
					// render new toolbar
					toolbar = $(oWysiwyg.options.toolbarHtml);
					oWysiwyg.ui.toolbar.replaceWith(toolbar);
					oWysiwyg.ui.toolbar = toolbar;
					oWysiwyg.ui.appendControls();
				});
			},
	
			clear: function (object) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					oWysiwyg.setContent("");
				});
			},
	
			console: console, // let our console be available for extensions
	
			destroy: function (object) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					oWysiwyg.destroy();
				});
			},
	
			"document": function (object) {
				// no chains because of return
				var oWysiwyg = object.data("wysiwyg");
	
				if (!oWysiwyg) {
					return undefined;
				}
	
				return $(oWysiwyg.editorDoc);
			},
	
			getContent: function (object) {
				// no chains because of return
				var oWysiwyg = object.data("wysiwyg");
	
				if (!oWysiwyg) {
					return undefined;
				}
	
				return oWysiwyg.getContent();
			},
	
			init: function (object, options) {
				return object.each(function () {
					var opts = $.extend(true, {}, options),
						obj;
	
					// :4fun:
					// remove this textarea validation and change line in this.saveContent function
					// $(this.original).val(content); to $(this.original).html(content);
					// now you can make WYSIWYG editor on h1, p, and many more tags
					if (("textarea" !== this.nodeName.toLowerCase()) || $(this).data("wysiwyg")) {
						return;
					}
	
					obj = new Wysiwyg();
					obj.init(this, opts);
					$.data(this, "wysiwyg", obj);
	
					$(obj.editorDoc).trigger("afterInit.wysiwyg");
				});
			},
	
			insertHtml: function (object, szHTML) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					oWysiwyg.insertHtml(szHTML);
				});
			},
	
			plugin: {
				listeners: {},
	
				bind: function (Wysiwyg) {
					var self = this;
	
					$.each(this.listeners, function (action, handlers) {
						var i, plugin;
	
						for (i = 0; i < handlers.length; i += 1) {
							plugin = self.parseName(handlers[i]);
	
							$(Wysiwyg.editorDoc).bind(action + ".wysiwyg", {plugin: plugin}, function (event) {
								$.wysiwyg[event.data.plugin.name][event.data.plugin.method].apply($.wysiwyg[event.data.plugin.name], [Wysiwyg]);
							});
						}
					});
				},
	
				exists: function (name) {
					var plugin;
	
					if ("string" !== typeof (name)) {
						return false;
					}
	
					plugin = this.parseName(name);
	
					if (!$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method]) {
						return false;
					}
	
					return true;
				},
	
				listen: function (action, handler) {
					var plugin;
	
					plugin = this.parseName(handler);
	
					if (!$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method]) {
						return false;
					}
	
					if (!this.listeners[action]) {
						this.listeners[action] = [];
					}
	
					this.listeners[action].push(handler);
	
					return true;
				},
	
				parseName: function (name) {
					var elements;
	
					if ("string" !== typeof (name)) {
						return false;
					}
	
					elements = name.split(".");
	
					if (2 > elements.length) {
						return false;
					}
	
					return {name: elements[0], method: elements[1]};
				},
	
				register: function (data) {
					if (!data.name) {
						console.error("Plugin name missing");
					}
	
					$.each($.wysiwyg, function (pluginName) {
						if (pluginName === data.name) {
							console.error("Plugin with name '" + data.name + "' was already registered");
						}
					});
	
					$.wysiwyg[data.name] = data;
	
					return true;
				}
			},
	
			removeFormat: function (object) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					oWysiwyg.removeFormat();
				});
			},
	
			save: function (object) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					oWysiwyg.saveContent();
				});
			},
	
			selectAll: function (object) {
				var oWysiwyg = object.data("wysiwyg"), oBody, oRange, selection;
	
				if (!oWysiwyg) {
					return this;
				}
	
				oBody = oWysiwyg.editorDoc.body;
				if (window.getSelection) {
					selection = oWysiwyg.getInternalSelection();
					selection.selectAllChildren(oBody);
				} else {
					oRange = oBody.createTextRange();
					oRange.moveToElementText(oBody);
					oRange.select();
				}
			},
	
			setContent: function (object, newContent) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					oWysiwyg.setContent(newContent);
				});
			},
	
			triggerControl: function (object, controlName) {
				return object.each(function () {
					var oWysiwyg = $(this).data("wysiwyg");
	
					if (!oWysiwyg) {
						return this;
					}
	
					if (!oWysiwyg.controls[controlName]) {
						console.error("Control '" + controlName + "' not exists");
					}
	
					oWysiwyg.triggerControl.apply(oWysiwyg, [controlName, oWysiwyg.controls[controlName]]);
				});
			},
	
			support: {
				prop: supportsProp
			},
	
			utils: {
				extraSafeEntities: [["<", ">", "'", '"', " "], [32]],
	
				encodeEntities: function (str) {
					var self = this, aStr, aRet = [];
	
					if (this.extraSafeEntities[1].length === 0) {
						$.each(this.extraSafeEntities[0], function (i, ch) {
							self.extraSafeEntities[1].push(ch.charCodeAt(0));
						});
					}
					aStr = str.split("");
					$.each(aStr, function (i) {
						var iC = aStr[i].charCodeAt(0);
						if ($.inArray(iC, self.extraSafeEntities[1]) && (iC < 65 || iC > 127 || (iC > 90 && iC < 97))) {
							aRet.push('&#' + iC + ';');
						} else {
							aRet.push(aStr[i]);
						}
					});
	
					return aRet.join('');
				}
			}
		};
	
		$.fn.wysiwyg = function (method) {
			var args = arguments, plugin;
	
			if ("undefined" !== typeof $.wysiwyg[method]) {
				// set argument object to undefined
				args = Array.prototype.concat.call([args[0]], [this], Array.prototype.slice.call(args, 1));
				return $.wysiwyg[method].apply($.wysiwyg, Array.prototype.slice.call(args, 1));
			} else if ("object" === typeof method || !method) {
				Array.prototype.unshift.call(args, this);
				return $.wysiwyg.init.apply($.wysiwyg, args);
			} else if ($.wysiwyg.plugin.exists(method)) {
				plugin = $.wysiwyg.plugin.parseName(method);
				args = Array.prototype.concat.call([args[0]], [this], Array.prototype.slice.call(args, 1));
				return $.wysiwyg[plugin.name][plugin.method].apply($.wysiwyg[plugin.name], Array.prototype.slice.call(args, 1));
			} else {
				console.error("Method '" +  method + "' does not exist on jQuery.wysiwyg.\nTry to include some extra controls or plugins");
			}
		};
		
		$.fn.getWysiwyg = function () {
			return $.data(this, "wysiwyg");
		};
	})(jQuery);
	
	
	
/**
 * Controls: Image plugin
 *
 * Depends on jWYSIWYG
 */
(function ($) {
	if (undefined === $.wysiwyg) {
		throw "wysiwyg.image.js depends on $.wysiwyg";
	}

	if (!$.wysiwyg.controls) {
		$.wysiwyg.controls = {};
	}

	/*
	 * Wysiwyg namespace: public properties and methods
	 */
	$.wysiwyg.controls.image = {
		init: function (Wysiwyg) {
			var self = this, elements, dialog, formImageHtml, dialogReplacements, key, translation,
				img = {
					alt: "",
					self: Wysiwyg.dom.getElement("img"), // link to element node
					src: "http://",
					title: ""
				};

			dialogReplacements = {
				legend	: "Insert Image",
				preview : "Preview",
				url     : "URL",
				title   : "Title",
				description : "Description",
				width   : "Width",
				height  : "Height",
				original : "Original W x H",
				"float"	: "Float",
				floatNone : "None",
				floatLeft : "Left",
				floatRight : "Right",
				submit  : "Insert Image",
				loading  : "loading",
				reset   : "Cancel"
			};

			formImageHtml = '<form class="wysiwyg" title="{legend}"><fieldset>' +
				'<label><img src="" alt="{preview}" width="100%"></label>' +
				'<label>{url}: <input type="text" name="src" value=""></label>' +
				'<label>{title}: <input type="text" name="imgtitle" value=""></label>' +
				'<label>{description}: <input type="text" name="description" value=""></label>' +
				'<label>{width} x {height}: <input type="text" name="width" value="" class="width integer"> x <input type="text" name="height" value="" class="height integer"></label><br>' +
				'<label>{float}: <select name="float">' + 
				'<option value="">{floatNone}</option>' +
				'<option value="left">{floatLeft}</option>' +
				'<option value="right">{floatRight}</option></select></label><hr>' +
				'<button class="button" id="wysiwyg_submit">{submit}</button> ' +
				'<button class="button" id="wysiwyg_reset">{reset}</button></fieldset></form>';

			for (key in dialogReplacements) {
				if ($.wysiwyg.i18n) {
					translation = $.wysiwyg.i18n.t(dialogReplacements[key], "dialogs.image");

					if (translation === dialogReplacements[key]) { // if not translated search in dialogs 
						translation = $.wysiwyg.i18n.t(dialogReplacements[key], "dialogs");
					}

					dialogReplacements[key] = translation;
				}

				formImageHtml = formImageHtml.replace("{" + key + "}", dialogReplacements[key]);
			}

			if (img.self) {
				img.src = img.self.src ? img.self.src : "";
				img.alt = img.self.alt ? img.self.alt : "";
				img.title = img.self.title ? img.self.title : "";
				img.width = img.self.width ? img.self.width : "";
				img.height = img.self.height ? img.self.height : "";
				img.asp = img.width/img.width;
			}

			if ($.modal) {
				elements = $(formImageHtml);
				elements = self.makeForm(elements, img);

				$.modal(elements, {
					onShow: function (dialog) {
						$("#wysiwyg_submit", dialog.data).click(function (e) {
							self.processInsert(dialog.container, Wysiwyg, img);

							$.modal.close();
							return false;
						});
						$("#wysiwyg_reset", dialog.data).click(function (e) {
							$.modal.close();
							return false;
						});
						$("fieldset", dialog.data).click(function (e) {
							e.stopPropagation();
						});
						
						$("select, input[type=text]", dialog).uniform();
						$('.integer', dialog).wl_Number();
						$('input[name="src"]', dialog).wl_URL();
						
					},
					maxWidth: Wysiwyg.defaults.formWidth,
					maxHeight: Wysiwyg.defaults.formHeight,
					overlayClose: true
				});
			} else if ($.fn.dialog) {
				elements = $(formImageHtml);
				elements = self.makeForm(elements, img);

				dialog = elements.appendTo("body");
				dialog.dialog({
					modal: true,
					resizable: false,
					open: function (ev, ui) {
						$("#wysiwyg_submit", dialog).click(function (e) {
							self.processInsert(dialog.container, Wysiwyg, img);

							$(dialog).dialog("close");
							return false;
						});
						$("#wysiwyg_reset", dialog).click(function (e) {
							$(dialog).dialog("close");
							return false;
						});
						$('fieldset', dialog).click(function (e) {
							e.stopPropagation();
						});
						$("select, input[type=text]", dialog).uniform();
						$('.width', dialog).wl_Number({
							step:10,
							onChange:function(value){
								$('.height', dialog).val(Math.ceil(value/(img.asp || 1)));
							}								
						});
						$('.height', dialog).wl_Number({
							step:10,
							onChange:function(value){
								$('.width', dialog).val(Math.floor(value*(img.asp || 1)));
							}								
						});
						$('input[name="src"]', dialog).wl_URL();
						
					},
					close: function (ev, ui) {
						dialog.dialog("destroy");
						dialog.remove();
					}
				});
			} else {
				if ($.browser.msie) {
					Wysiwyg.ui.focus();
					Wysiwyg.editorDoc.execCommand("insertImage", true, null);
				} else {
					elements = $("<div/>")
						.css({"position": "fixed",
							"z-index": 2000,
							"left": "50%", "top": "50%", "background": "rgb(0, 0, 0)",
							"margin-top": -1 * Math.round(Wysiwyg.defaults.formHeight / 2),
							"margin-left": -1 * Math.round(Wysiwyg.defaults.formWidth / 2)})
						.html(formImageHtml);
					elements = self.makeForm(elements, img);

					$("#wysiwyg_submit", elements).click(function (event) {
						self.processInsert(elements, Wysiwyg, img);

						$(elements).remove();
						return false;
					});
					$("#wysiwyg_reset", elements).click(function (event) {
						if ($.browser.msie) {
							Wysiwyg.ui.returnRange();
						}

						$(elements).remove();
						return false;
					});
					
					$("select, input[type=text]", dialog).uniform();
					$('.integer', dialog).wl_Number();
					$('input[name="src"]', dialog).wl_URL();
					
					$("body").append(elements);
					elements.click(function(e) {
						e.stopPropagation();
					});
				}
			}

			$(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
		},

		processInsert: function (context, Wysiwyg, img) {
			var image,
				url = $('input[name="src"]', context).val(),
				title = $('input[name="imgtitle"]', context).val(),
				description = $('input[name="description"]', context).val(),
				width = $('input[name="width"]', context).val(),
				height = $('input[name="height"]', context).val(),
				styleFloat = $('select[name="float"]', context).val(),
				style = [],
				found,
				baseUrl;

			if (Wysiwyg.options.controlImage.forceRelativeUrls) {
				baseUrl = window.location.protocol + "//" + window.location.hostname;
				if (0 === url.indexOf(baseUrl)) {
					url = url.substr(baseUrl.length);
				}
			}

			if (img.self) {
				// to preserve all img attributes
				$(img.self).attr("src", url)
					.attr("title", title)
					.attr("alt", description)
					.css("float", styleFloat);

				if (width.toString().match(/^[0-9]+(px|%)?$/)) {
					$(img.self).css("width", width);
				} else {
					$(img.self).css("width", "");
				}

				if (height.toString().match(/^[0-9]+(px|%)?$/)) {
					$(img.self).css("height", height);
				} else {
					$(img.self).css("height", "");
				}
				
				Wysiwyg.saveContent();
			} else {
				found = width.toString().match(/^[0-9]+(px|%)?$/);
				if (found) {
					if (found[1]) {
						style.push("width: " + width + ";");
					} else {
						style.push("width: " + width + "px;");
					}
				}

				found = height.toString().match(/^[0-9]+(px|%)?$/);
				if (found) {
					if (found[1]) {
						style.push("height: " + height + ";");
					} else {
						style.push("height: " + height + "px;");
					}
				}

				if (styleFloat.length > 0) {
					style.push("float: " + styleFloat + ";");
				}

				if (style.length > 0) {
					style = ' style="' + style.join(" ") + '"';
				}

				image = "<img src='" + url + "' title='" + title + "' alt='" + description + "'" + style + "/>";
				Wysiwyg.insertHtml(image);
			}
		},

		makeForm: function (form, img) {
			form.find("input[name=src]").val(img.src);
			form.find("input[name=imgtitle]").val(img.title);
			form.find("input[name=description]").val(img.alt);
			form.find('input[name="width"]').val(img.width);
			form.find('input[name="height"]').val(img.height);
			form.find('img').attr("src", img.src);
			img.asp = img.width/img.height;
			
			form.find("input[name=src]").bind("change", function () {
				var image = new Image();
				var text = $('#wysiwyg_submit',form).find('span').text();
				form.find('img').removeAttr("src");
				
				$('#wysiwyg_submit',form).prop('disabled',true).find('span').text('wait...');
				
				image.onload = function(){
					
					form.find('img').attr("src", image.src);
					img.asp = image.width/image.height;
					form.find('input[name="width"]').val(image.width);
					form.find('input[name="height"]').val(image.height);
					$('#wysiwyg_submit',form).find('span').text(text);
					$('#wysiwyg_submit',form).prop('disabled',false);
					
				};
				image.src = this.value; 
			});

			return form;
		}
	};

	$.wysiwyg.insertImage = function (object, url, attributes) {
		return object.each(function () {
			var Wysiwyg = $(this).data("wysiwyg"),
				image,
				attribute;

			if (!Wysiwyg) {
				return this;
			}

			if (!url || url.length === 0) {
				return this;
			}

			if ($.browser.msie) {
				Wysiwyg.ui.focus();
			}

			if (attributes) {
				Wysiwyg.editorDoc.execCommand("insertImage", false, "#jwysiwyg#");
				image = Wysiwyg.getElementByAttributeValue("img", "src", "#jwysiwyg#");

				if (image) {
					image.src = url;

					for (attribute in attributes) {
						if (attributes.hasOwnProperty(attribute)) {
							image.setAttribute(attribute, attributes[attribute]);
						}
					}
				}
			} else {
				Wysiwyg.editorDoc.execCommand("insertImage", false, url);
			}

			Wysiwyg.saveContent();

			$(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");

			return this;
		});
	};
})(jQuery);


/**
 * Controls: Table plugin
 * 
 * Depends on jWYSIWYG
 */
(function ($) {
	if (undefined === $.wysiwyg) {
		throw "wysiwyg.table.js depends on $.wysiwyg";
	}

	if (!$.wysiwyg.controls) {
		$.wysiwyg.controls = {};
	}

	var insertTable = function (colCount, rowCount, filler) {
		if (isNaN(rowCount) || isNaN(colCount) || rowCount === null || colCount === null) {
			return;
		}

		var i, j, html = ['<table border="1" style="width: 100%;"><tbody>'];

		colCount = parseInt(colCount, 10);
		rowCount = parseInt(rowCount, 10);

		if (filler === null) {
			filler = "&nbsp;";
		}
		filler = "<td>" + filler + "</td>";

		for (i = rowCount; i > 0; i -= 1) {
			html.push("<tr>");
			for (j = colCount; j > 0; j -= 1) {
				html.push(filler);
			}
			html.push("</tr>");
		}
		html.push("</tbody></table>");

		return this.insertHtml(html.join(""));
	};

	/*
	 * Wysiwyg namespace: public properties and methods
	 */
	$.wysiwyg.controls.table = function (Wysiwyg) {
		var dialog, colCount, rowCount, formTableHtml,
			formTextLegend = "Insert table",
			formTextCols   = "Count of columns",
			formTextRows   = "Count of rows",
			formTextSubmit = "Insert table",
			formTextReset  = "Cancel";

		if ($.wysiwyg.i18n) {
			formTextLegend = $.wysiwyg.i18n.t(formTextLegend, "dialogs.table");
			formTextCols = $.wysiwyg.i18n.t(formTextCols, "dialogs.table");
			formTextRows = $.wysiwyg.i18n.t(formTextRows, "dialogs.table");
			formTextSubmit = $.wysiwyg.i18n.t(formTextSubmit, "dialogs.table");
			formTextReset = $.wysiwyg.i18n.t(formTextReset, "dialogs");
		}

		formTableHtml = '<form class="wysiwyg" title="' + formTextLegend + '"><fieldset>' +
			'<label>' + formTextCols + ': <input type="text" name="colCount" value="3" class="integer" /></label><br>' +
			'<label>' + formTextRows + ': <input type="text" name="rowCount" value="3" class="integer" /></label><hr>' +
			'<button class="button" id="wysiwyg_submit">' + formTextSubmit + '</button> ' +
			'<button class="button" id="wysiwyg_reset">' + formTextReset + '</button></fieldset></form>';

		if (!Wysiwyg.insertTable) {
			Wysiwyg.insertTable = insertTable;
		}

		if ($.fn.modal) {
			$.modal(formTableHtml, {
				onShow: function (dialog) {
					$("#wysiwyg_submit", dialog.data).click(function (e) {
						e.preventDefault();
						rowCount = $('input[name="rowCount"]', dialog.data).val();
						colCount = $('input[name="colCount"]', dialog.data).val();

						Wysiwyg.insertTable(colCount, rowCount, Wysiwyg.defaults.tableFiller);
						$.modal.close();
					});
					$("#wysiwyg_reset", dialog.data).click(function (e) {
						e.preventDefault();
						$.modal.close();
					});
					
					$("select, input[type=text]", dialog).uniform();
					$('.integer', dialog).wl_Number();
					
				},
				maxWidth: Wysiwyg.defaults.formWidth,
				maxHeight: Wysiwyg.defaults.formHeight,
				overlayClose: true
			});
		} else if ($.fn.dialog) {
			dialog = $(formTableHtml).appendTo("body");
			dialog.dialog({
				modal: true,
				resizable: false,
				open: function (event, ui) {
					$("#wysiwyg_submit", dialog).click(function (e) {
						e.preventDefault();
						rowCount = $('input[name="rowCount"]', dialog).val();
						colCount = $('input[name="colCount"]', dialog).val();

						Wysiwyg.insertTable(colCount, rowCount, Wysiwyg.defaults.tableFiller);
						$(dialog).dialog("close");
					});
					$("#wysiwyg_reset", dialog).click(function (e) {
						e.preventDefault();
						$(dialog).dialog("close");
					});
					
					$("select, input[type=text]", dialog).uniform();
					$('.integer', dialog).wl_Number();
					
				},
				close: function (event, ui) {
					dialog.dialog("destroy");
					dialog.remove();
				}
			});
		} else {
			colCount = prompt(formTextCols, "3");
			rowCount = prompt(formTextRows, "3");

			Wysiwyg.insertTable(colCount, rowCount, Wysiwyg.defaults.tableFiller);
		}

		$(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
	};

	$.wysiwyg.insertTable = function (object, colCount, rowCount, filler) {
		return object.each(function () {
			var Wysiwyg = $(this).data("wysiwyg");

			if (!Wysiwyg.insertTable) {
				Wysiwyg.insertTable = insertTable;
			}

			if (!Wysiwyg) {
				return this;
			}

			Wysiwyg.insertTable(colCount, rowCount, filler);
			$(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");

			return this;
		});
	};
})(jQuery);
	
/**
 * Controls: Link plugin
 *
 * Depends on jWYSIWYG
 *
 * By: Esteban Beltran (academo) <sergies@gmail.com>
 */
(function ($) {
	if (undefined === $.wysiwyg) {
		throw "wysiwyg.link.js depends on $.wysiwyg";
	}

	if (!$.wysiwyg.controls) {
		$.wysiwyg.controls = {};
	}

	/*
	* Wysiwyg namespace: public properties and methods
	*/
	$.wysiwyg.controls.link = {
		init: function (Wysiwyg) {
			var self = this, elements, dialog, url, a, selection,
				formLinkHtml, formTextLegend, formTextUrl, formTextTitle, formTextTarget,
				formTextSubmit, formTextReset,
				baseUrl;

			formTextLegend  = "Insert Link";
			formTextUrl     = "Link URL";
			formTextTitle   = "Link Title";
			formTextTarget  = "Link Target";
			formTextSubmit  = "Insert Link";
			formTextReset   = "Cancel";

			if ($.wysiwyg.i18n) {
				formTextLegend = $.wysiwyg.i18n.t(formTextLegend, "dialogs.link");
				formTextUrl    = $.wysiwyg.i18n.t(formTextUrl, "dialogs.link");
				formTextTitle  = $.wysiwyg.i18n.t(formTextTitle, "dialogs.link");
				formTextTarget = $.wysiwyg.i18n.t(formTextTarget, "dialogs.link");
				formTextSubmit = $.wysiwyg.i18n.t(formTextSubmit, "dialogs.link");
				formTextReset  = $.wysiwyg.i18n.t(formTextReset, "dialogs");
			}

			formLinkHtml = '<form class="wysiwyg" title="' + formTextLegend + '"><fieldset>' +
				'<label>' + formTextUrl + ': <input type="text" name="linkhref" value=""/></label>' +
				'<label>' + formTextTitle + ': <input type="text" name="linktitle" value=""/></label>' +
				'<label>' + formTextTarget + ': <input type="text" name="linktarget" value=""/></label><hr>' +
				'<button class="button" id="wysiwyg_submit">' + formTextSubmit + '</button> ' +
				'<button class="button" id="wysiwyg_reset">' + formTextReset + '</button></fieldset></form>';

			a = {
				self: Wysiwyg.dom.getElement("a"), // link to element node
				href: "http://",
				title: "",
				target: ""
			};

			if (a.self) {
				a.href = a.self.href ? a.self.href : a.href;
				a.title = a.self.title ? a.self.title : "";
				a.target = a.self.target ? a.self.target : "";
			}

			if ($.fn.dialog) {
				elements = $(formLinkHtml);
				elements.find("input[name=linkhref]").val(a.href);
				elements.find("input[name=linktitle]").val(a.title);
				elements.find("input[name=linktarget]").val(a.target);

				if ($.browser.msie) {
					dialog = elements.appendTo(Wysiwyg.editorDoc.body);
				} else {
					dialog = elements.appendTo("body");
				}

				dialog.dialog({
					modal: true,
					resizable: false,
					open: function (ev, ui) {
						$("#wysiwyg_submit", dialog).click(function (e) {
							e.preventDefault();

							var url = $('input[name="linkhref"]', dialog).val(),
								title = $('input[name="linktitle"]', dialog).val(),
								target = $('input[name="linktarget"]', dialog).val(),
								baseUrl;

							if (Wysiwyg.options.controlLink.forceRelativeUrls) {
								baseUrl = window.location.protocol + "//" + window.location.hostname;
								if (0 === url.indexOf(baseUrl)) {
									url = url.substr(baseUrl.length);
								}
							}

							if (a.self) {
								if ("string" === typeof (url)) {
									if (url.length > 0) {
										// to preserve all link attributes
										$(a.self).attr("href", url).attr("title", title).attr("target", target);
									} else {
										$(a.self).replaceWith(a.self.innerHTML);
									}
								}
							} else {
								if ($.browser.msie) {
									Wysiwyg.ui.returnRange();
								}

								//Do new link element
								selection = Wysiwyg.getRangeText();
								img = Wysiwyg.dom.getElement("img");

								if ((selection && selection.length > 0) || img) {
									if ($.browser.msie) {
										Wysiwyg.ui.focus();
									}

									if ("string" === typeof (url)) {
										if (url.length > 0) {
											Wysiwyg.editorDoc.execCommand("createLink", false, url);
										} else {
											Wysiwyg.editorDoc.execCommand("unlink", false, null);
										}
									}

									a.self = Wysiwyg.dom.getElement("a");

									$(a.self).attr("href", url).attr("title", title);

									/**
									 * @url https://github.com/akzhan/jwysiwyg/issues/16
									 */
									$(a.self).attr("target", target);
								} else if (Wysiwyg.options.messages.nonSelection) {
									$.dialog(Wysiwyg.options.messages.nonSelection);
								}
							}

							Wysiwyg.saveContent();

							$(dialog).dialog("close");
						});
						$("#wysiwyg_reset", dialog).click(function (e) {
							e.preventDefault();
							$(dialog).dialog("close");
						});
					
						$("select, input", dialog).uniform();
						$('input[name="linkhref"]', dialog).wl_URL();
						
					},
					close: function (ev, ui) {
						dialog.dialog("destroy");
						dialog.remove();
					}
				});
			} else {
				if (a.self) {
					url = window.prompt("URL", a.href);

					if (Wysiwyg.options.controlLink.forceRelativeUrls) {
						baseUrl = window.location.protocol + "//" + window.location.hostname;
						if (0 === url.indexOf(baseUrl)) {
							url = url.substr(baseUrl.length);
						}
					}

					if ("string" === typeof (url)) {
						if (url.length > 0) {
							$(a.self).attr("href", url);
						} else {
							$(a.self).replaceWith(a.self.innerHTML);
						}
					}
				} else {
					//Do new link element
					selection = Wysiwyg.getRangeText();
					img = Wysiwyg.dom.getElement("img");

					if ((selection && selection.length > 0) || img) {
						if ($.browser.msie) {
							Wysiwyg.ui.focus();
							Wysiwyg.editorDoc.execCommand("createLink", true, null);
						} else {
							url = window.prompt(formTextUrl, a.href);

							if (Wysiwyg.options.controlLink.forceRelativeUrls) {
								baseUrl = window.location.protocol + "//" + window.location.hostname;
								if (0 === url.indexOf(baseUrl)) {
									url = url.substr(baseUrl.length);
								}
							}

							if ("string" === typeof (url)) {
								if (url.length > 0) {
									Wysiwyg.editorDoc.execCommand("createLink", false, url);
								} else {
									Wysiwyg.editorDoc.execCommand("unlink", false, null);
								}
							}
						}
					} else if (Wysiwyg.options.messages.nonSelection) {
						window.alert(Wysiwyg.options.messages.nonSelection);
					}
				}

				Wysiwyg.saveContent();
			}

			$(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
		}
	};

	$.wysiwyg.createLink = function (object, url) {
		return object.each(function () {
			var oWysiwyg = $(this).data("wysiwyg"),
				selection;

			if (!oWysiwyg) {
				return this;
			}

			if (!url || url.length === 0) {
				return this;
			}

			selection = oWysiwyg.getRangeText();

			if (selection && selection.length > 0) {
				if ($.browser.msie) {
					oWysiwyg.ui.focus();
				}
				oWysiwyg.editorDoc.execCommand("unlink", false, null);
				oWysiwyg.editorDoc.execCommand("createLink", false, url);
			} else if (oWysiwyg.options.messages.nonSelection) {
				window.alert(oWysiwyg.options.messages.nonSelection);
			}
		});
	};
})(jQuery);

/**
 * Controls: Element CSS Wrapper plugin
 *
 * Depends on jWYSIWYG
 * 
 * By Yotam Bar-On (https://github.com/tudmotu)
 */
(function ($) {		
	if (undefined === $.wysiwyg) {
		throw "wysiwyg.cssWrap.js depends on $.wysiwyg";
	}
	/* For core enhancements #143
	$.wysiwyg.ui.addControl("cssWrap", {
		visible : false,
		groupIndex: 6,
		tooltip: "CSS Wrapper",
		exec: function () { 
				$.wysiwyg.controls.cssWrap.init(this);
			}
	}
	*/	
	if (!$.wysiwyg.controls) {
		$.wysiwyg.controls = {};
	}

	/*
	 * Wysiwyg namespace: public properties and methods
	 */
	$.wysiwyg.controls.cssWrap = {
		init: function (Wysiwyg) {
			var self = this, formWrapHtml, key, translation,
			dialogReplacements = {
				legend	: "Wrap Element",
				wrapperType : "Wrapper Type",
				ID : "ID",
				"class" : "Class",
				wrap  : "Wrap",
				unwrap: "Unwrap",
				cancel   : "Cancel"
			};

			formWrapHtml = '<form class="wysiwyg" title="{legend}"><fieldset>' +
				'<label>{wrapperType}:<select name="type"><option value="span">Span</option><option value="div">Div</option></select></label><br>' +
				'<label>{ID}:<input name="id" type="text"></label>' + 
				'<label>{class}:<input name="class" type="text" ></label><hr>' +
				'<button class="cssWrap-unwrap" style="display:none;">{unwrap}</button> ' +
				'<button class="cssWrap-submit">{wrap}</button> ' +
				'<button class="cssWrap-cancel">{cancel}</button></fieldset></form>';

			for (key in dialogReplacements) {
				if ($.wysiwyg.i18n) {
					translation = $.wysiwyg.i18n.t(dialogReplacements[key]);
					if (translation === dialogReplacements[key]) { // if not translated search in dialogs 
						translation = $.wysiwyg.i18n.t(dialogReplacements[key], "dialogs");
					}
					dialogReplacements[key] = translation;
				}
				formWrapHtml = formWrapHtml.replace("{" + key + "}", dialogReplacements[key]);
			}
			if (!$(".wysiwyg-dialog-wrapper").length) {
				$(formWrapHtml).appendTo("body");
				$("form.wysiwyg").dialog({
					modal: true,
					resizable: false,
					open: function (ev, ui) {
						$this = $(this);
						var range	= Wysiwyg.getInternalRange(), common;
						// We make sure that there is some selection:
						if (range) {
							if ($.browser.msie) {
								Wysiwyg.ui.focus();
							}
							common	= $(range.commonAncestorContainer);
						} else {
							alert("You must select some elements before you can wrap them.");
							$this.dialog("close");
							return 0;
						}
						var $nodeName = range.commonAncestorContainer.nodeName.toLowerCase();
						// If the selection is already a .wysiwygCssWrapper, then we want to change it and not double-wrap it.
						if (common.parent(".wysiwygCssWrapper").length) {
							alert(common.parent(".wysiwygCssWrapper").get(0).nodeName.toLowerCase());
							$this.find("select[name=type]").val(common.parent(".wysiwygCssWrapper").get(0).nodeName.toLowerCase());
							$this.find("select[name=type]").attr("disabled", "disabled");
							$this.find("input[name=id]").val(common.parent(".wysiwygCssWrapper").attr("id"));
							$this.find("input[name=class]").val(common.parent(".wysiwygCssWrapper").attr("class").replace('wysiwygCssWrapper ', ''));
							// Add the "unwrap" button:
							$("form.wysiwyg").find(".cssWrap-unwrap").show();
							$("form.wysiwyg").find(".cssWrap-unwrap").click(function(e) {
								e.preventDefault();
								if ($nodeName !== "body") {
									common.unwrap();
								}
								$this.dialog("close");
								return 1;
							});
						}
						// Submit button.
						$("form.wysiwyg").find(".cssWrap-submit").click(function(e) {
							e.preventDefault();
							var $wrapper = $("form.wysiwyg").find("select[name=type]").val();
							var $id = $("form.wysiwyg").find("input[name=id]").val();
							var $class = $("form.wysiwyg").find("input[name=class]").val();
							if ($nodeName !== "body") {
								// If the selection is already a .wysiwygCssWrapper, then we want to change it and not double-wrap it.
								if (common.parent(".wysiwygCssWrapper").length) {
									common.parent(".wysiwygCssWrapper").attr("id", $class);
									common.parent(".wysiwygCssWrapper").attr("class", $class);
								} else {
									common.wrap('<'+$wrapper+' id="'+$id+'" class="'+"wysiwygCssWrapper "+$class+'"/>');
								}
							} else {
								// Currently no implemntation for if $nodeName == 'body'.
							}
							$this.dialog("close");
						});
						// Cancel button.
						$("form.wysiwyg").find(".cssWrap-cancel").click(function(e) {
							e.preventDefault();
							$this.dialog("close");
							return 1;
						});
						$("form.wysiwyg").find("select, input[type=text]").uniform();
					},
					close: function () {
						$(this).dialog("destroy");
						$(this).remove();
					}
				});
				Wysiwyg.saveContent();
			}
			$(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
			return 1;
		}
	}
})(jQuery);
});

	
